package controllers;

import play.*;
import play.mvc.*;

import java.util.*;

import models.*;

@With(Secure.class)
public class Admin extends CRUD{

	/**
	 * Instancie des variables de session(session.put())
	 * Met ces variables dans des variables de rendu(render.args())
	 */
	@Before
	static void setConnectedUser() {
		if(Security.isConnected()) {
			if(!session.contains("agent_fullname")){
				Agent agent = Agent.find("nomUtilisateur", Security.connected()).first();
				Fonction gestFonct=Fonction.find("id_fonction like ?", "FONCT").first();
				Fonction gestTer=Fonction.find("id_fonction like ?", "TERRI").first();
				Fonction admin=Fonction.find("id_fonction like ?", "ADM").first();
				Fonction chef_CIS=Fonction.find("id_fonction like ?", "RCIS").first();
				Fonction formateur=Fonction.find("id_fonction like ?", "FOR").first();
				List<CIS> centres=CIS.find("responsable.id like ?", agent.id).fetch();
				boolean resp=!centres.isEmpty();
				/*
				 * Compte le nombre d'autorisation en attente pour les CIS où l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				List<Candidat> listeCandidats=new ArrayList<Candidat>();
				if(agent.fonction.contains(chef_CIS) || resp){
					Iterator<CIS> i=centres.iterator();
					while(i.hasNext()){
						List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", i.next().id, "AAUT").fetch();
						listeCandidats.addAll(cand);
					}
					session.put("nb_demande_auto", listeCandidats.size());
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
					long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
					session.put("nb_demande_valid_admin", nbValidAdmin);
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					session.put("nb_demande_annul_admin", nbAnnulAdmin);
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente pour le groupement dont l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(gestTer)){
					long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable like ? and demandeAnnulation is not true", "AVAL", agent);
					long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.id like ? and etatCandid.id_etatcandid not like ? or etatCandid.nom not like ?", agent.id, "ANN", "REF");
					session.put("nb_demande_valid_terri", nbValidTerri);
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					session.put("nb_demande_annul_terri", nbAnnulTerri);
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}
				
				/*
				 * Création des variables de session
				 */
				
				/*
				 * groupementResp_id représente l'id du groupement de l'agent si celui-ci est le responsable
				 * Sinon l'id du groupement auquel il appartient s'il possède la fonction gestionnaireTerritorial
				 */
				Groupement gpmt=Groupement.find("responsable like ?", agent).first();
				if(gpmt!=null){
					session.put("groupementResp_id", gpmt.id);
				}
				else if(agent.fonction.contains(gestTer)){
					session.put("groupementResp_id", agent.cis.groupement.id);
				}
				
				int aujourdhui=Calendar.getInstance().get(Calendar.YEAR);
				session.put("nomUtilisateur", agent.nomUtilisateur);
				session.put("anneeEnCours", aujourdhui);
				session.put("agent_id", agent.id);
				session.put("agent_niv", agent.niv.niv);
				session.put("agent_cis", agent.cis);
				session.put("agent_grpt", agent.cis.groupement);
				session.put("chef_CIS", agent.fonction.contains(chef_CIS));
				session.put("agent_email", agent.email);
				session.put("agent_fullname", agent.fullname());
				session.put("agent_responsable", resp);
				session.put("agent_grade", agent.grade.toString());
				session.put("gestionnaireFonct", (agent.fonction.contains(gestFonct)));
				session.put("gestionnaireTerri", agent.fonction.contains(gestTer));
				session.put("formateur", agent.fonction.contains(formateur));
				session.put("admin", agent.fonction.contains(admin));
				session.put("CISService", agent.cis.nom);
				/*
				 * Compte le nombre de validations en attente pour les fmpa et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=FMPA.count("etat.nom like ?", "Attente de validation");
					session.put("nb_valid_fmpa", nbValidAdmin);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(gestTer)){
					long nbValidTerri=FMPA.count("etat.nom like ? and cis.groupement.nom like ?", "Attente de validation", session.get("agent_grpt"));
					session.put("nb_valid_fmpa", nbValidTerri);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(chef_CIS) || resp){
					long nbValidCis=FMPA.count("etat.nom like ? and cis.nom like ?", "Attente de validation", session.get("CISService"));
					session.put("nb_valid_fmpa", nbValidCis);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				System.out.println(session.get("nb_valid_fmpa"));
				/*
				 * Création des variables de rendu
				 */
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				if(agent.niv.id != 0){
					session.put("agent_for", agent.niv);
					renderArgs.put("agent_for", session.get("agent_for"));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
			else{
				/*
				 * Création des variables de rendu si les variables de session existent
				 */
				if(session.contains("nb_demande_valid_terri") || session.contains("nb_demande_annul_terri")){
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				if(session.contains("nb_demande_valid_admin") || session.contains("nb_demande_annul_admin")){
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				renderArgs.put("agent_for", session.get("agent_for"));
				if(session.contains("nb_valid_fmpa")){
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
		}
	}

	/**
	 * Menu de l'administration
	 */
	static public void ihm(){

		render();
	}

	
	/**
	 * Affiche le formulaire de gestion des droits en fonction de la fonction de l'agent
	 */
	static public void gestionDroit(){
		List<Agent> agents=new ArrayList<Agent>();
		List<CIS> cis;
		List<Fonction> droits;
		//si l'agent est admin, affiche tous les agents
		if(session.get("admin").equals("true")){
			agents=Agent.find("order by nom").fetch();
			cis=CIS.find("order by nom").fetch();
			droits=Fonction.findAll();
			render(droits, agents, cis);
		}
		//si l'agent est gestionnaire territorial affiche tous les agents du territoire
		else if(session.get("agent_responsable").equals("true")){
			cis=CIS.find("responsable.id like ? order by nom", Long.decode(session.get("agent_id"))).fetch();
			CIS c=CIS.find("nom like ?", session.get("CISService")).first();
			if(session.get("chef_CIS").equals("true")&&!cis.contains(c)){
				cis.add(c);
			}
			Iterator<CIS> i=cis.iterator();
			while(i.hasNext()){
				List<Agent> a=Agent.find("cis like ? order by nom", i.next()).fetch();
				agents.addAll(a);
			}
			droits=Fonction.find("id_fonction like ? or id_fonction like ?", "FOR", "RCIS").fetch();
			render(droits, agents, cis);
		}
		//si l'agent est chef de centre, affiche tous les agents du centre
		else if(session.get("chef_CIS").equals("true")){
			CIS c=CIS.find("nom like ?", session.get("CISService")).first();
			agents=Agent.find("cis like ? order by nom", c).fetch();
			droits=Fonction.find("nom like ?", "Formateur").fetch();
			render(droits, agents);
		}
		//sinon l'accès est refusé
		else{
			render("@accessDenied");
		}
	}

	/**
	 * Enlève le droit d'id droitIdEnlever de l'agent d'id agentEnlever
	 * @param droitIdEnlever
	 * @param agentEnlever
	 */
	static public void enleverDroit(long droitIdEnlever, long agentEnlever){
		// Gestion des erreurs
		if(droitIdEnlever==0){
			flash.error("Il n'y a pas de droit à enlever");
		}
		else if(agentEnlever==0){
			flash.error("Aucun agent n'a été sélectionné");
		}
		//sinon enlève le droit de l'agent si ce n'est pas lui
		else{
			Agent agent=Agent.findById(agentEnlever);
			if(agent.nomUtilisateur.equals(session.get("nomUtilisateur"))){
				flash.error("Vous ne pouvez pas vous enlever vos droits");
			}
			else{
				Fonction fonction=Fonction.findById(droitIdEnlever);
				agent.fonction.remove(fonction);
				agent.save();
				flash.success("L'agent "+agent.fullname()+" n'a plus le droit "+fonction.nom);
			}
		}
		gestionDroit();
	}

	/**
	 * Modifie l'affichage de la liste en fonction des droits de l'agent d'id agent 
	 * @param agent
	 */
	static public void filtreDroits(long agent){
		Agent agentObj=Agent.findById(agent);
		List<Fonction> fonctions=agentObj.fonction;
		if(session.get("agent_responsable").equals("true")){
			List<Fonction> f=Fonction.find("id_fonction not like ? and id_fonction not like ?", "FOR", "RCIS").fetch();
			fonctions.removeAll(f);
		}else if(session.get("chef_CIS").equals("true")){
			List<Fonction> f=Fonction.find("id_fonction not like ?", "FOR").fetch();
			fonctions.removeAll(f);
		}
		render(fonctions);
	}

	/**
	 * Modifie l'affichage de la liste d'agent en fonction du CIS sélectionné d'id cis
	 * @param cis
	 */
	static public void filtreAgents(long cis){
		List<Agent> agents=Agent.find("cis.id like ? order by nom", cis).fetch();
		render(agents);
	}

	
	/**
	 * Donne un le droit d'id droitId à l'agent d'id agent
	 * @param agent
	 * @param droitId
	 */
	static public void sauverDroit(long agent, long droitId){
		//gestion des erreurs
		if(droitId==0){
			flash.error("Il n'y a pas de droit à ajouter");
		}
		else if(agent==0){
			flash.error("Aucun agent n'a été sélectionné");
		}
		//sinon ajoute le droit à l'agent s'il ne le possède pas déjà
		else{
			Agent agentObj=Agent.findById(agent);
			Fonction fonction=Fonction.findById(droitId);
			if(agentObj.fonction.contains(fonction)){
				flash.error("L'agent "+agentObj.nom+" "+agentObj.prenom+" a déjà le droit "+fonction.nom);
			}
			else{
				agentObj.fonction.add(fonction);
				fonction.agent.add(agentObj);
				fonction.save();
				agentObj.save();
				flash.success("L'agent "+agentObj.nom+" "+agentObj.prenom+" a maintenant le droit "+fonction.nom);
			}
		}
		gestionDroit();
	}

	/**
	 * Active le compte de l'agent d'id agent avec le mot de passe mdp
	 * @param mdp
	 * @param agent
	 */
	static public void activerCompteSave(String mdp, long agent){
		Agent agentObj=Agent.findById(agent);
		//Gestion des erreurs
		if(agentObj==null){
			flash.error("Aucun agent selecionné");
		}
		else if(mdp.equals(null) || mdp.equals("d41d8cd98f00b204e9800998ecf8427e")){
			flash.error("Vous n'avez pas rentré de mot de passe");
		}
		//Enregistre le mot de passe
		else{
			agentObj.password=mdp;
			agentObj.save();
			flash.success("Le compte de "+agentObj.prenom+" "+agentObj.nom+" a été activé.");
		}
		activerCompte();
	}

	/**
	 * Modifie la liste des agents en fonction du cis d'id cis
	 * @param cis
	 */
	static public void filtreAgentsActiverCompte(long cis){
		List<Agent> agents;
		if(cis==0){
			agents=Agent.find("password is null order by nom").fetch();
		}
		else{
			agents=Agent.find("cis.id equals ? and password is null order by nom", cis).fetch();
			System.out.println(agents);
		}
		render(agents);
	}

	/**
	 * Affiche la liste des agents dont le mot de passe a pour valeur null ou ""
	 */
	static public void activerCompte(){
		if(session.get("admin").equals("true")){
			List<CIS> centres=CIS.find("order by nom").fetch();
			List<Agent> agents=Agent.find("password is null or password like ? order by nom", "").fetch();
			render(agents, centres);
		}
		else if(session.get("chef_CIS").equals("true")){
			List<Agent> agents=Agent.find("cis.nom like ? and (password is null or password like ?) order by nom", session.get("CISService"), "").fetch();
			render(agents);
		}
		else{
			render("@accessDenied");
		}
	}
}
